package com.rbn.stockmobiledevices.entradas.internal;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.transaction.annotation.Transactional;

import com.rbn.stockmobiledevices.dispositivos.Dispositivo;
import com.rbn.stockmobiledevices.dispositivos.DispositivoManager;
import com.rbn.stockmobiledevices.dispositivos.internal.HibernateDispositivoManager;
import com.rbn.stockmobiledevices.entradas.Entrada;
import com.rbn.stockmobiledevices.entradas.EntradaManager;
import com.rbn.stockmobiledevices.entradas.Estado;
import com.rbn.stockmobiledevices.proveedores.Proveedor;
import com.rbn.stockmobiledevices.proveedores.ProveedorManager;
import com.rbn.stockmobiledevices.proveedores.internal.HibernateProveedorManager;
import com.rbn.stockmobiledevices.utils.AutoCompleteElement;

public class HibenateEntradaManager implements EntradaManager {
	
	private SessionFactory sessionFactory;
	
	public HibenateEntradaManager(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
	
	@SuppressWarnings("unchecked")
	@Transactional(readOnly = true)
	public List<Entrada> getAll(){
		return getCurrentSession().createQuery("from Entrada").list();
	}
	
	@Transactional(readOnly = true)
	public Entrada getById(Long imei){
		return (Entrada) getCurrentSession().get(Entrada.class, imei);
	}
	
	@Transactional
	public void update(Entrada entrada){
		getCurrentSession().update(entrada);
	}
	
	@Transactional
	public void remove(Entrada entrada){
		getCurrentSession().delete(entrada);
	}
	
	@SuppressWarnings("unchecked")
	@Transactional(readOnly = true)
	public List<Entrada> getPaginadoEntrada(Integer startPosition, Integer pageSize,
			String imei, String dispositivo, Long proveedor, Date fecha) {
		Session session = getCurrentSession();
		String hlqQuery = "from Entrada e";

		String whereClause = "";
		if((imei!=null && imei.length()>0) || (dispositivo !=null && dispositivo.length()>0) || proveedor!=null || fecha!=null){
			hlqQuery += " where ";
		
			if (imei != null && imei.length() > 0) {
				whereClause += "and  e.imei like :imei ";
			}
			if(dispositivo !=null && dispositivo.length()>0){
				whereClause += "and  e.dispositivo.modelo like :dispositivo ";
			}
			if(proveedor != null){
				whereClause += "and  e.proveedor.id = :proveedor ";
			}
			if(fecha != null){
				whereClause += "and  e.fechaEntrada between :fecha_desde and :fecha_hasta ";
			}
			
			whereClause = whereClause.substring(whereClause.indexOf("and ")+4 ,whereClause.length());
			hlqQuery += whereClause;
		}
		
		hlqQuery += " order by e.fechaEntrada desc, e.imei";
		Query q = session.createQuery(hlqQuery);
		
		if (imei != null && imei.length() > 0) {
			q.setString("imei", imei);
		}
		if(dispositivo !=null && dispositivo.length()>0){
			q.setString("dispositivo", "%"+dispositivo+"%");
		}
		if(proveedor != null){
			q.setLong("proveedor", proveedor);
		}
		if(fecha != null){
			Date fecha_desde = null;
			Date fecha_hasta = null;
			GregorianCalendar cal = new GregorianCalendar();
			cal.setTime(fecha);
			cal.set(Calendar.HOUR, 0);
			cal.set(Calendar.MINUTE, 0);
			cal.set(Calendar.SECOND, 0);
			cal.set(Calendar.MILLISECOND, 0);
			
			fecha_desde = cal.getTime();
			cal.add(Calendar.HOUR, 23);
			cal.add(Calendar.MINUTE, 59);
			cal.add(Calendar.SECOND, 59);
			
			fecha_hasta = cal.getTime(); 
			q.setDate("fecha_desde", fecha_desde);
			q.setDate("fecha_hasta", fecha_hasta);
		}
		
		if(startPosition!=null && pageSize!=null){
			q.setFirstResult(startPosition);
			q.setMaxResults(pageSize);
		}
		
		return q.list();
	}

	@Transactional
	public Boolean remove(Long imei) {
		Entrada e = this.getById(imei);
		if(e==null)
			return false;
		getCurrentSession().delete(e);
		return true;
	}

	@Transactional
	public void save(Entrada entrada) {
		getCurrentSession().save(entrada);
	}
	
	@Transactional(readOnly = true)
	public Dispositivo getDispositivoById(String codigo) {
		DispositivoManager dispositivoMgr = new HibernateDispositivoManager(sessionFactory);
		return dispositivoMgr.getById(codigo);
	}
	
	@Transactional(readOnly = true)
	public Proveedor getProveedorById(int id) {
		ProveedorManager proveedorMgr = new HibernateProveedorManager(sessionFactory);
		return proveedorMgr.getById(id);
	}
	
	@Transactional(readOnly = true)
	public Estado getEstadoById(int id) {
		return (Estado) getCurrentSession().get(Estado.class, id);
	}
	
	@Transactional
	public void updateEstado(Estado estado) {
		getCurrentSession().update(estado);
	}
	
	@Transactional
	public Boolean removeEstado(int id) {
		Estado e = getEstadoById(id);
		if(e==null)
			return false;
		getCurrentSession().delete(e);
		return true;
		
	}
	
	@Transactional
	public Integer saveEstado(Estado estado) {
		getCurrentSession().save(estado);
		estado = getEstadoByUnicEstado(estado.getEstado());
		return estado.getId();
	}
	
	public Estado getEstadoByUnicEstado(String estado){
		Session session = getCurrentSession();
		String hlqQuery = "from Estado e";
		hlqQuery += " where e.estado = :estado";
		hlqQuery += " order by e.estado";
		Query q = session.createQuery(hlqQuery);
		q.setString("estado", estado);
		
		return (Estado)q.uniqueResult();
	}
	
	@Transactional(readOnly = true)
	public List<AutoCompleteElement> getDispositivosOptionsByModelo(String search) {
		DispositivoManager dispositivoMgr = new HibernateDispositivoManager(sessionFactory);
		List<Dispositivo> d = dispositivoMgr.getPaginadoDispositivos(null, null, search);
		
		List<AutoCompleteElement> elements = new ArrayList<AutoCompleteElement>();
		AutoCompleteElement element = null;
		for (Dispositivo dispositivo : d) {
			element = new AutoCompleteElement(dispositivo.getCodigo(), dispositivo.getModelo());
			elements.add(element);
		}
		return elements;
	}

	@Transactional(readOnly = true)
	public List<AutoCompleteElement> getProveedorOptionsByModelo(String search) {
		ProveedorManager proveedorMgr = new HibernateProveedorManager(sessionFactory);
		List<Proveedor> proveedores = proveedorMgr.getByNombre(search);
		
		List<AutoCompleteElement> elements = new ArrayList<AutoCompleteElement>();
		AutoCompleteElement element = null;
		for (Proveedor proveedor : proveedores) {
			element = new AutoCompleteElement(String.valueOf(proveedor.getId()), proveedor.getNombre());
			elements.add(element);
		}
		return elements;
	}
	
	@SuppressWarnings("unchecked")
	@Transactional(readOnly = true)
	public List<AutoCompleteElement> getEstadoOptionsByModelo(String search) {
		List<AutoCompleteElement> elements = new ArrayList<AutoCompleteElement>();
		Session session = getCurrentSession();
		String hlqQuery = "from Estado e";

		if (search != null && search.trim().length() > 0) {
			hlqQuery += " where e.estado like '%" + search + "%'";
		}
		hlqQuery += " order by id";
		Query q = session.createQuery(hlqQuery);
		
		List<Estado> estados = (List<Estado>) q.list();
		AutoCompleteElement element = null;
		for (Estado estado : estados) {
			element = new AutoCompleteElement(String.valueOf(estado.getId()), estado.getEstado());
			elements.add(element);
		}
		return elements;
	}
	
	protected Session getCurrentSession() {
		return sessionFactory.getCurrentSession();
	}
}
